
package modele;

import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Statement;
import java.util.ArrayList;
import java.util.List;
import modele.exceptions.InformationIndisponibleException;
import modele.exceptions.MatiereInexistanteException;

/**
 * Class Matiere permet de représenter une module avec son nom et son enseignant principal
 */
public class Matiere
{
    private int id;
    private String nom; //le 'sigle' = nom raccourci
    private String nomComplet;
    private Intervenant enseignant;

    /**
     * Constructeur permettant de remplir toutes les informations de la matière
     */
    public Matiere(int id, String nom, String nomComplet, Intervenant i)
    {
        this.id = id;
        this.nom = nom;
        this.nomComplet = nomComplet;
        enseignant = i;
    }

    /**
     * Constructeur partiel de Matiere, ne doit être utilisé que lorsqu'on n'a
     * pas besoin de savoir l'enseignant
     * @param id : identifiant de la matière
     * @param nom : nom ou 'sigle' de la matière
     * @param nomComplet : nom complet de la matière
     */
    public Matiere(int id, String nom, String nomComplet)
    {
        this(id, nom, nomComplet, null);
    }

    /**
     * Constructeur partiel de Matiere, ne doit être utilisé que lorsqu'on n'a
     * pas besoin de savoir les autres informations
     * @param id : identifiant de la matière
     */
    public Matiere(int id)
    {
        this(id, null, null, null);
    }

    /**
     * Renvoie l'identifiant de la matière
     * @return l'identifiant
     */
    public int getId()
    {
        return id;
    }

    /**
     * Renvoie le nom complet de la matière
     * @return le nom
     */
    public String getNomComplet()
    {
        return nomComplet;
    }

    /**
     * Renvoie le nom de la matière pour un affichage classique
     * @return le nom
     */
    @Override
    public String toString()
    {
        return nom;
    }

    /**
     * Renvoie l'enseignant principal de la matière s'il est renseigné, une exception sinon
     * @return l'intervenant demandé
     */
    public Intervenant getEnseignant() throws InformationIndisponibleException
    {
        if(enseignant == null)
            throw new InformationIndisponibleException(Intervenant.class, this.getClass());

        return enseignant;
    }

    //Méthodes statiques d'accès à la base de données

    /**
     * Renvoie la liste de toutes les matières avec leur nom court et complet
     * @return la liste demandée
     */
    public static List<Matiere> getToutesLesMatieres() throws SQLException
    {
        List<Matiere> resultat = new ArrayList<Matiere>();

        String requete = "Select id_module, sigle, nom from module order by sigle;";
        Connection c = ConnexionBD.getConnection();
        Statement s = c.createStatement();
        ResultSet rs = s.executeQuery(requete);

        while(rs.next())
        {
            int idm = (Integer) rs.getObject(1);
            String nom = (String) rs.getObject(2);
            String nomComplet = (String) rs.getObject(3);
            Matiere m = new Matiere(idm, nom, nomComplet);
            resultat.add(m);
        }

        c.close();

        return resultat;

     }

    /**
     * Renvoie la liste des matières d'une année de formation avec leur nom court et complet.
     * Si la formation est M1 FIC ou M1 FA, on va renvoyer les matières de M1.
     * Si la formation est M2 FIC ou M2 FA, on va renvoyer les matières de M2.
     * @return la liste demandée
     */
    public static List<Matiere> getMatieres(Formation form) throws SQLException
    {
        List<Matiere> resultat = new ArrayList<Matiere>();

        String requete = "Select id_module, sigle, nom from module where id_formation = ? order by sigle;";
        Connection c = ConnexionBD.getConnection();
        PreparedStatement ps = c.prepareStatement(requete);

        int id_formation = 1;
        if(form.getNomFormation().equals("M2 FIC") || form.getNomFormation().equals("M2 FA"))
            id_formation = 3;

        ps.setInt(1, id_formation);
        ResultSet rs = ps.executeQuery();

        while(rs.next())
        {
            int idm = (Integer) rs.getObject(1);
            String nom = (String) rs.getObject(2);
            String nomComplet = (String) rs.getObject(3);
            Matiere m = new Matiere(idm, nom, nomComplet);
            resultat.add(m);
        }

        c.close();

        return resultat;

    }
 
    /**
     * Renvoie la matière correspondant à un identifiant si elle existe, une exception sinon.
     * Seulement les nom et prénom de l'enseignant sont renseignés
     * @param id_matiere : l'identifiant de la matière
     * @return la matière demandée
     * @throws MatiereInexistanteException si la matière n'existe pas
     */
    public static Matiere getMatiere(int id_matiere) throws MatiereInexistanteException, SQLException
    {
        Matiere resultat = null;

        String requete = "Select m.sigle, m.nom, f.id_formateur, f.nom, f.prenom from module m, formateur f where m.id_module = ? and m.id_formateur = f.id_formateur;";
        Connection c = ConnexionBD.getConnection();
        PreparedStatement ps = c.prepareStatement(requete);
        ps.setInt(1, id_matiere);
        ResultSet rs = ps.executeQuery();

        if(rs.next())
        {
            //La matière existe

            String nomMatiere = (String) rs.getObject(1);
            String nomCompletMatiere = (String) rs.getObject(2);
            Integer idFormateur = (Integer) rs.getObject(3);
            String nomEnseignant = (String) rs.getObject(4);
            String prenomEnseignant = (String) rs.getObject(5);

            Intervenant i = new Intervenant(idFormateur, nomEnseignant, prenomEnseignant);

            resultat = new Matiere(id_matiere, nomMatiere, nomCompletMatiere, i);

        }
        else
        {
            //La matière n'existe pas
            throw new MatiereInexistanteException();
        }

        c.close();

        return resultat;
    }

    /**
     * Renvoie la liste des retours formulés sur une matière si elle existe, une exception sinon.
     * On ne récupère que les retours qui ne sont pas vides
     * Seulement le nom et prénom de l'étudiant est renseigné.
     * @param id_matiere : l'identifiant de la matière demandée
     * @return la liste des retours demandée (sans indication de la matière)
     * @throws MatiereInexistanteException si la matière n'existe pas
     */
    public static List<RetourSurMatiere> getRetours(int id_matiere) throws MatiereInexistanteException, SQLException
    {
        List<RetourSurMatiere> resultat = new ArrayList<RetourSurMatiere>();

        //Vérifier que la matière existe
        Matiere m = Matiere.getMatiere(id_matiere);

        String requete = "Select id_rsm, texte, r.id_etudiant, nom, prenom from retour_sur_module r, etudiant e where id_module = ? and r.id_etudiant = e.id_etudiant and texte <> '' order by nom, prenom;";
        Connection c = ConnexionBD.getConnection();
        PreparedStatement ps = c.prepareStatement(requete);
        ps.setInt(1, id_matiere);
        ResultSet rs = ps.executeQuery();

        while(rs.next())
        {
            int idrsm = (Integer) rs.getObject(1);
            String texte = (String) rs.getObject(2);
            int idetu = (Integer) rs.getObject(3);
            String nom = (String) rs.getObject(4);
            String prenom = (String) rs.getObject(5);
            resultat.add(new RetourSurMatiere(idrsm, texte, new Etudiant(idetu, nom, prenom)));
        }

        c.close();

        return resultat;

    }

}
